<template>
  <div style="box-sizing: border-box">
    <el-dialog
            top="7vh"
            v-model="transData.dialogVisible"
            :title="transData.title"
            :close-on-click-modal="false"
            width="50%"
    >
      <template #title>
        <span style="font-size: 18px;">{{transData.title}}</span>
        <el-popover
                placement="bottom"
                title="小提示"
                :width="400"
                @show="popoverShow"
                trigger="hover"
        >
          <ul class="dialog_popover_ul">
            <li>目录：代表直接插入根节点的父节点(与主页菜单平级)</li>
            <li>菜单：可以点击跳转页面的节点</li>
            <li>权限：访问的权限标识</li>
            <li>菜单编码：唯一值，用户根据编码获取对应的菜单信息</li>
            <li>菜单路由：前端路由对象的path属性(前缀可不加'/')</li>
            <li>菜单组件：前端路由对象的component属性(前缀可不加'/')</li>
            <li>排序：值越小，菜单显示越靠前(最小值为1)</li>
            <li>是否启用：默认只能启用(禁用)没有子集的目录，菜单、权限则不受限制</li>
            <li>显示状态：如果状态为隐藏，则所有页面隐藏该节点，且不参与权限相关的操作</li>
            <li>路由菜单：点击是否可跳转页面</li>
            <li>菜单缓存：keep_alive值</li>
            <li>目前只能插入的菜单层级为两级</li>
          </ul>
          <template #reference>
            <el-badge :value="badgeFlag ? 'new' : ''" type="danger">
              <i class="fa fa-tag" style="color: #CCC; margin-left: 20px; cursor: pointer; font-size: 18px"/>
            </el-badge>
          </template>
        </el-popover>
      </template>
      <el-scrollbar height="480px">
      <div style="padding-right: 15px">
        <!--label-position="left"-->
        <el-form ref="form" :rules="rules" :model="form" label-width="80px" :disabled="operation == 'see'" status-icon size="small">
          <el-form-item v-if="false">
            <el-input v-model="form.id"></el-input>
          </el-form-item>
          <el-form-item label="菜单类型">
            <el-button-group>
              <el-button @click="menuTypeClick(menuType.catalogue)" :type="form.menuType === menuType.catalogue ? 'primary' : ''" :disabled="operation != 'add'"><i class="fa fa-folder-open-o" style="margin-right: 6px"/>目录</el-button>
              <el-button @click="menuTypeClick(menuType.menu)" :type="form.menuType === menuType.menu ? 'primary' : ''" :disabled="operation != 'add'"><i class="fa fa-list-ul" style="margin-right: 6px"/>菜单</el-button>
              <el-button @click="menuTypeClick(menuType.button)" :type="form.menuType === menuType.button ? 'primary' : ''" :disabled="operation != 'add'"><i class="fa fa-shield" style="margin-right: 6px"/>权限</el-button>
            </el-button-group>
          </el-form-item>
          <transition name="fade">
            <el-form-item
                    v-if="form.menuType === menuType.menu || form.menuType === menuType.button"
                    label="父级菜单"
                    prop="parent">
              <el-select v-model="form.parentId" @visible-change="parentMenuSelectVisible" ref="parentMenuSelect" placeholder="请选择父级菜单" style="width: 100%" v-if="!menuSelectLoading" clearable>
                <el-option
                        v-for="item in parentMenuSelectList"
                        :key="1"
                        :label="item.title"
                        :value="item.id">
                </el-option>
                <template #empty>
                  <el-scrollbar max-height="380px">
                    <div style="padding: 10px; border-radius: 5px; background: cyan">
                      <el-input v-model="parentMenuFilterText" placeholder="输入名称进行搜索" v-if="parentMenuTreeList.length" style="padding-bottom: 5px" clearable></el-input>
                      <el-tree :data="parentMenuTreeList"
                               ref="parentMenuTree"
                               :filter-node-method="filterParentMenuNode"
                               node-key="id"
                               default-expand-all
                               :props="defaultProps"
                               style="border-radius: 5px">
                        <template #default="{ node, data }">
                          <div :title="data.id == form.parentId ? '已选' : data.enabled !== enabledState.enabled ? '禁用' : '可用'" style="width: 100%;display: flex;justify-content: space-between">
                            <!--左边显示文字-->
                            <span v-if="data.enabled == enabledState.enabled">
                              <!--已选-->
                              <span v-if="data.id == form.parentId" style="color: #409EFF">{{ data.title }}</span>
                              <!--可用-->
                              <span v-else style="color: green">{{ data.title }}</span>
                            </span>
                            <!--禁用-->
                            <span v-else style="color: red">{{ data.title }}</span>

                            <!--右边选择按钮-->
                            <span style="margin-right: 15px; font-size: 16px">
                              <span v-if="data.enabled == enabledState.enabled && data.id != form.parentId" @click.stop="parentNodeClick(data)" title="选择">
                                <icon class="fa fa-hand-pointer-o" style="color: green"/>
                              </span>
                              <span v-else-if="data.id != form.parentId">
                                <icon class="fa fa-ban" style="color: red"/>
                              </span>
                              <span v-else-if="data.id == form.parentId">
                                <icon class="fa fa-hand-peace-o" style="color: #409EFF"/>
                              </span>
                            </span>
                          </div>
                        </template>
                      </el-tree>
                    </div>
                  </el-scrollbar>
                </template>
              </el-select>
              <i v-else class="el-icon-loading"/>
            </el-form-item>
          </transition>
          <el-form-item label="菜单标题" prop="title">
            <el-input v-model.trim="form.title" maxlength="20" clearable placeholder="请输入菜单标题"></el-input>
          </el-form-item>
          <transition name="fade">
            <el-form-item label="菜单编码" prop="code">
              <el-input v-model.trim="form.code" maxlength="20" clearable placeholder="请输入菜单编码"></el-input>
            </el-form-item>
          </transition>
          <transition name="fade">
            <el-form-item label="菜单路径" v-if="form.menuType == menuType.menu" prop="path">
              <el-input v-model.trim="form.path" maxlength="30" clearable placeholder="请输入菜单路径(前缀可不加'/')"></el-input>
            </el-form-item>
          </transition>
          <transition name="fade">
            <el-form-item label="菜单组件" v-if="form.menuType == menuType.menu" prop="component">
              <el-input v-model.trim="form.component" maxlength="30" clearable placeholder="请输入菜单组件(前缀可不加'/')"></el-input>
            </el-form-item>
          </transition>
          <el-form-item label="图标" v-if="form.menuType != menuType.button" prop="icon">
          <el-select v-model="form.icon" placeholder="Select" clearable style="width: 100%">
            <el-option
                    v-for="item in 15"
                    :key="item"
                    :label="item"
                    :value="item"
                    :disabled="item == 2"
            >
            </el-option>
          </el-select>
          </el-form-item>
          <el-row :gutter="20">
            <el-col :span="8">
              <el-form-item label="排序" prop="sort">
                <el-tooltip
                        content="值越小,排序越靠前,可输入小数"
                        placement="top-end"
                >
                  <el-input-number v-model="form.sort" :min="1" :step="1" :max="500" :precision="2" style="width: 100%"/>
                </el-tooltip>
              </el-form-item>
            </el-col>
            <el-col :span="6">
            </el-col>
            <el-col :span="10">
              <el-form-item label="是否启用" prop="enabled">
                <!--<el-radio v-model="form.enabled" :label="enabledState.enabled">是</el-radio>
                <el-radio v-model="form.enabled" :label="enabledState.disabled">否</el-radio>-->
                <i v-if="enabledHiddenFlag" class="el-icon-loading"/>
                <el-tooltip
                        v-else
                        :content="enabledHiddenDisabledFlag ? '当前节点包含子集，此操作已被禁用！' : form.enabled == enabledState.enabled ? '当前：启用' : '当前：禁用'"
                        placement="top-start"
                >
                  <el-radio-group v-model="form.enabled" :disabled="enabledHiddenDisabledFlag" :fill="form.enabled == enabledState.disabled ? 'red' : ''">
                    <el-radio-button :label="enabledState.enabled">是</el-radio-button>
                    <el-radio-button :label="enabledState.disabled">否</el-radio-button>
                  </el-radio-group>
                </el-tooltip>
              </el-form-item>
              <!--<el-form-item label="是否启用" prop="enabled">
                <el-switch v-model="form.enabled" inline-prompt active-text="是" inactive-text="否">
                </el-switch>
              </el-form-item>-->
            </el-col>
          </el-row>
          <el-row :gutter="20" justify="space-between">
            <el-col :span="8">
              <el-form-item label="显示状态" prop="hidden">
                <i v-if="enabledHiddenFlag" class="el-icon-loading"/>
                <el-tooltip
                        v-else
                        :content="enabledHiddenDisabledFlag ? '当前节点包含子集，此操作已被禁用！' : form.hidden == hiddenFlag.display ? '当前：显示' : '当前：隐藏'"
                        placement="top-start"
                >
                  <el-radio-group v-model="form.hidden" :disabled="enabledHiddenDisabledFlag" :fill="form.hidden != hiddenFlag.display ? 'red' : ''">
                    <el-radio-button :label="hiddenFlag.display">显示</el-radio-button>
                    <el-radio-button :label="hiddenFlag.hidden">隐藏</el-radio-button>
                  </el-radio-group>
                </el-tooltip>
              </el-form-item>
            </el-col>
              <el-col :span="8">
                <transition name="fade">
                  <el-form-item label="路由菜单" v-if="form.menuType == menuType.menu" prop="isRoute">
                    <el-radio-group v-model="form.isRoute" :fill="form.isRoute != 1 ? 'red' : ''">
                      <el-radio-button :label="1">是</el-radio-button>
                      <el-radio-button :label="0">否</el-radio-button>
                    </el-radio-group>
                  </el-form-item>
                </transition>
            </el-col>
            <el-col :span="8">
              <transition name="fade">
              <el-form-item label="菜单缓存" v-if="form.menuType == menuType.menu" prop="keepAlive">
                <el-radio-group v-model="form.keepAlive" :fill="form.keepAlive != 1 ? 'red' : ''">
                  <el-radio-button :label="1">是</el-radio-button>
                  <el-radio-button :label="0">否</el-radio-button>
                </el-radio-group>
              </el-form-item>
              </transition>
            </el-col>
          </el-row>
        </el-form>
      </div>
      </el-scrollbar>
      <template #footer>
      <span class="dialog-footer" v-if="operation != 'see'">
        <el-button @click="transData.dialogVisible = false" size="small">取消</el-button>
        <el-button type="primary" @click="formSubmit('form')" :loading="submitLoading" :disabled="operation == 'see'" size="small"
        >{{submitLoading ? '提交中' : '提交'}}</el-button
        >
      </span>
      </template>
    </el-dialog>
  </div>
</template>

<script>
  import constants from '@/config/constants/systemConstants';
  import { service } from '@/utils/api';

  export default {
    name: "AddOrEdit",
    data() {
      //自定义校验规则
      const validateParent = (rule, value, rollback) => {
        if(this.form.parentId) {
          rollback();
        } else {
          rollback('父级菜单不能为空');
        }
      };
      const validateTitle = (rule, value, callback) => {
        if(value) {
          this.$api.getRequest(`/permission/queryTitleRepeated?title=${value}&id=${this.form.id ? this.form.id : ''}`).then(res => {
            if(res.success) {
              if(res.data) {
                callback(new Error("标题已重复"));
              } else {
                callback();
              }
            } else {
              callback(new Error())
            }
          })
        } else {
          callback(new Error("标题不能为空"))
        }
      };
      const validateCode = (rule, value, callback) => {
        if(value) {
          this.$api.getRequest(`/permission/queryCodeRepeated?code=${value}&id=${this.form.id ? this.form.id : ''}`).then(res => {
            if(res.success) {
              if(res.data) {
                callback(new Error("编码已重复"));
              } else {
                callback();
              }
            } else {
              callback(new Error())
            }
          })
        } else {
          callback(new Error("编码不能为空"))
        }
      };
      return {
        //操作该组件的类型
        operation: undefined,
        //权限类型常量
        menuType: {
          //目录
          catalogue: constants.menuType.catalogue,
          //菜单
          menu: constants.menuType.menu,
          //按钮
          button: constants.menuType.button
        },
        enabledState: {
          enabled: constants.enabled,
          disabled: constants.disabled,
        },
        hiddenFlag: {
          display: constants.hiddenFlag.display,
          hidden: constants.hiddenFlag.hidden
        },
        //表单对象
        form: {
          parentId: undefined,
          menuType: constants.menuType.menu,
          sort: 5,
          enabled: constants.enabled,
          isRoute: 1,
          keepAlive: 1,
          hidden: constants.hiddenFlag.display
        },
        //表单校验规则
        rules: {
          parent: [{required: true, validator: validateParent, trigger: 'change'}],
          title: [{required: true, validator: validateTitle, trigger: 'blur'}],
          code: [{required: true, validator: validateCode, trigger: 'blur'}],
          path: [{required: true, message: '路径不能为空', trigger: ['change','blur']}],
          component: [{required: true, message: '组件不能为空', trigger: ['change', 'blur']}],
          icon: [{required: true, message: '图标不能为空', trigger: ['change','blur']}],
          sort: [{required: true, message: '排序不能为空', trigger: ['change','blur']}],
          enabled: [{required: true, message: '启用状态不能为空', trigger: ['change','blur']}],
          hidden: [{required: true, message: '显隐状态不能为空', trigger: ['change','blur']}],
          isRoute: [{required: true, message: '是否路由不能为空', trigger: ['change','blur']}],
          keepAlive: [{required: true, message: '菜单缓存不能为空', trigger: ['change','blur']}],
        },
        parentMenuFilterText: '',
        //选择父节点树的数据
        parentMenuTreeList: [],
        //选择父节点选择器的数据
        parentMenuSelectList: [],
        defaultProps: {
          children: 'children',
          label: 'title',
        },
        badgeFlag: constants.badgeFlag,
        //加载按钮
        submitLoading: false,
        //父级菜单选择器加载flag
        menuSelectLoading: true,
        //启用和隐藏按钮加载flag
        enabledHiddenFlag: false,
        //启用和隐藏按钮禁用flag
        enabledHiddenDisabledFlag: false,
      }
    },
    created() {
      if(this.transData.operation) {
        if(this.transData.operation == constants.operation.add) {
          this.operation = 'add';
        } else if(this.transData.operation == constants.operation.edit) {
          this.operation = 'edit';
          this.form = this.transData.data;
        } else if(this.transData.operation == constants.operation.see) {
          this.operation = 'see';
          this.form = this.transData.data;
        }
        //如果该节点是目录，并且是编辑状态，则查询该目录是否有子集，如果有子集则不可以修改其状态及显示状态
        if(this.operation == 'edit' && this.form.menuType == this.menuType.catalogue) {
          this.enabledHiddenFlag = true;
          this.$api.getRequest(`/permission/queryHasChildren/${this.form.id}`).then(res => {
            if(res.success) {
              this.enabledHiddenFlag = false;
              if(res.data) {
                //禁用掉菜单状态和菜单显示状态
                this.enabledHiddenDisabledFlag = true;
              }
            }
          })
        }
        if(this.form.menuType == this.menuType.menu || this.form.menuType == this.menuType.button) {
          this.getParentList();
        }
      } else {
        this.$message.error('系统异常，未检测到操作类型！');
        throw new Error('未选择操作类型！');
      }
    },
    methods: {
      //获取父级信息
      getParentList() {
        this.menuSelectLoading = true;
        this.$api.getRequest('/permission/findCatalogueAndMenu').then(res => {
          if(res.success) {
            this.parentMenuTreeList = res.data;
            if(this.operation != 'add' && (this.form.menuType == this.menuType.menu || this.form.menuType == this.menuType.button)) {
              //获取父级节点的名称
              this.findTitleByParentId(this.form.parentId, this.parentMenuTreeList);
            }
            this.menuSelectLoading = false;
          }
        })
      },
      //在编辑状态下，根据parentId遍历所有数据找到其对应的title信息
      findTitleByParentId(parentId, list) {
        let findFlag = false;
        for (let i = 0; i < list.length; i++) {
          if(parentId == list[i].id) {
            this.parentMenuSelectList = [{id: parentId, title: list[i].title}];
            findFlag = true;
            break;
          }
          if(list[i].children instanceof Array && list[i].children.length && !findFlag) {
            this.findTitleByParentId(parentId, list[i].children);
          }
        }
      },
      menuTypeClick(type) {
        this.form.menuType = type;
      },

      //父菜单选择器操作
      filterParentMenuNode(value, data) {
        if (!value) return true;
        return data.title.indexOf(value) !== -1;
      },
      parentNodeClick(data) {
        if(data.enabled !== this.enabledState.enabled) {
          this.$message.warning('该节点已被禁用不可添加！');
        } else {
          this.$refs.parentMenuSelect.blur();
          this.parentMenuSelectList = [{id: data.id, title: data.title}];
          this.form.parentId = data.id;
        }
      },
      //选择父级的选择器获取焦点时触发
      parentMenuSelectVisible(flag) {
        //true：打开 false：关闭
        if(flag) {
          //清空真正的值，展示虚拟菜单树
          this.parentMenuSelectList = [];
        }
      },
      /*表单操作*/
      //表单提交
      formSubmit(formName) {
        this.submitLoading = true;
        this.$refs[formName].validate((valid) => {
          if(valid) {
            //表单对象
            let tempForm = {};
            switch (this.form.menuType) {
              case this.menuType.catalogue:
                tempForm = {
                  'id': this.form.id,
                  'title': this.form.title,
                  'icon': this.form.icon,
                  'code': this.form.code,
                  'enabled': this.form.enabled,
                  'sort': this.form.sort,
                  'hidden': this.form.hidden,
                  'menuType': this.form.menuType
                };
                break;
              case this.menuType.menu:
                tempForm = this.form;
                break;
              case this.menuType.button:
                tempForm = {
                  'id': this.form.id,
                  'parentId': this.form.parentId,
                  'title': this.form.title,
                  'code': this.form.code,
                  'enabled': this.form.enabled,
                  'sort': this.form.sort,
                  'hidden': this.form.hidden,
                  'menuType': this.form.menuType
                };
                break;
            }
            if(this.operation == 'add') {
              this.$api.postRequest('/permission/', {...tempForm}).then(res => {
                if(res.success) {
                  this.$emit('refreshTable');
                  this.transData.dialogVisible = false;
                }
                this.submitLoading = false;
              })
            } else if(this.operation == 'edit') {
              this.$api.putRequest('/permission/', {...tempForm}).then(res => {
                if(res.success) {
                  this.$emit('refreshTable');
                  this.transData.dialogVisible = false;
                }
                this.submitLoading = false;
              })
            }
          } else {
            this.submitLoading = false;
            return false;
          }
        });
      },

      /*其他操作*/
      //徽章操作
      popoverShow() {
        this.badgeFlag = false;
        constants.badgeFlag = false;
      },
      enabledClick(value) {
        alert(value)
      }
    },
    props: {
      transData: {
        type: Object,
        default: () => {},
        require: true,
      }
    },
    watch: {
      //监听父级菜单选择时搜索区域的内容
      parentMenuFilterText(val) {
        this.$refs.parentMenuTree.filter(val);
      }
    }
  }
</script>

<style scoped>
  /*详情窗口dialog样式*/
  /deep/ .el-dialog{
    /*dialog高度*/
    /*height: 100%;*/
    border-radius: 5px;
  }
  /*dialog距离顶部高度*/
  >>>.el-dialog__body {
    padding: 10px 5px 5px 0;
  }

  /*表单样式*/
  .el-form-item {
    margin-bottom: 20px;
  }

  /*最后一个元素*/
  /*.el-row:last-child {
    margin-top: 5px;
  }*/

  .el-row {
    margin-top: 5px;
  }

  /*树节点样式*/
  /deep/ .el-tree-node__content {
    height: 35px;
    border-radius: 5px;
  }

  /*菜单提示的popover*/
  .dialog_popover_ul li {
    margin-bottom: 5px;
  }

  /*组件过渡样式*/
  .fade-enter-active,
  .fade-leave-active {
    transition: opacity 0.5s ease;
  }

  .fade-enter-from,
  .fade-leave-to {
    opacity: 0;
  }

</style>
